﻿using DGZImp.Core.EFDbContext;
using DGZImp.Core.Exceptions;
using DGZImp.Core.Extensions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;

namespace DGZImp.DianduProject.Services
{
    public class AmesSyncService : IDependency
    {
        public ISqlSugarClient Db = AutofacContainerModule.GetService<ServiceDbContext>()?.SqlSugarClient;
        public IConfiguration _config;
        public HttpClient client = null;
        public static IHttpClientFactory _httpClientFactory { get; set; }

        public string url = "";
        public string db = "";
        public string userName = "";
        public string password = "";

        public static int? uid = 0;

        public ILogger<AmesSyncService> logger { get; set; }

        public AmesSyncService(IConfiguration configuration, IHttpClientFactory httpClientFactory)
        {
            _config = configuration;
            _httpClientFactory = httpClientFactory;
            this.url = _config["Interfaces:AnTaiMes:Url"];
            this.db = _config["Interfaces:AnTaiMes:Db"];
            this.userName = _config["Interfaces:AnTaiMes:UserName"];
            this.password = _config["Interfaces:AnTaiMes:Password"];
        }

        /// <summary>
        /// 调用AMES接口 通用方法
        /// </summary>
        public async Task<JObject> Call(string service, string method, List<dynamic> args)
        {
            client = _httpClientFactory.CreateClient();
            var json = new
            {
                jsonrpc = "2.0",
                method = "call",
                @params = new { service = service, method = method, args = args },
                id = Guid.NewGuid(),
            };
            try
            {
                Console.WriteLine(JsonConvert.SerializeObject(json));
                var content = new StringContent(JsonConvert.SerializeObject(json), Encoding.UTF8, "application/json");
                //logger.LogInformation("---开始请求AMES获取数据---");
                //logger.LogInformation(JsonConvert.SerializeObject(json));
                client.Timeout = TimeSpan.FromSeconds(300);
                var response = await client.PostAsync(url, content);
                response.EnsureSuccessStatusCode();
                var responseString = await response.Content.ReadAsStringAsync();
                //logger.LogInformation(responseString);
                var responseJson = JObject.Parse(responseString);
                return responseJson;
            }
            catch (Exception e)
            {
                throw new AppException(e.Message);
            }
        }

        public async Task<JObject> CallSearchRead(string model, List<object> domain, List<string> fields, object pageData)
        {
            var param = new List<object>();
            param.Add(db);
            //if (uid == null || uid == 0)
                uid = await GetOdooUid(userName, password);
            param.Add(uid);
            param.Add(password);
            param.Add(model);
            param.Add("search_read");
            param.Add(new List<object> { domain, fields });
            param.Add(pageData);
            JObject data = null;
            try
            {
                data = await Call("object", "execute_kw", param);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, $"获取aMES数据失败，请求内容：{JsonConvert.SerializeObject(param)}，错误信息：{ex.Message}");
                throw new AppException(ex.ToString());
            }
            return data;
        }

        /// <summary>
        /// 获取odoo平台用户id
        /// </summary>
        public async Task<int?> GetOdooUid(string username, string password)
        {
            var res = await Call("common", "login", new List<dynamic> { db, username, password });
            return Convert.ToInt32(res["result"]);
        }

        /// <summary>
        /// 具体业务调用
        /// 如果报错则会再调用一次
        /// </summary>
        public async Task<JObject> BusinessCall(string service, string method, List<dynamic> args)
        {
            JObject data = null;
            try
            {
                //if (uid == null || uid == 0) 
                    uid = await GetOdooUid(userName, password);
                args[1] = uid;
                data = await Call(service, method, args);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, $"获取aMES数据失败，{service}，{method}，{JsonConvert.SerializeObject(args)}，信息：{ex.Message}");
                throw new AppException(ex.ToString());
            }
            return data;
        } 
        /// <summary>
          /// CCD同步生产任务单
          /// </summary>
          /// 
        public async Task<object> SyncProductionTask_CCD(string taskNo = "")
        {
            var isSingle = taskNo.IsValuable();

            //同步的任务工序
            var typeArray = new[] { "white" };

            var qDomain = new List<object> {

                new List<object> { "production_type", "in", typeArray }
            };

            if (isSingle)
            {
                qDomain.Add(new List<object> { "name", "=", taskNo });
            }
            else
            {
                qDomain.Add(new List<object> { "state", "=", "in_production" });
            }

            var qFields = new List<string> {
                "grade",
                "prodcut_spec",
                "raw_resume_weight",
                "state",
                "schedule_id",
                "product_id",
                "partner_id",
                "name",
                "raw_lot_id",
                "date_planned",
                "product_qty",
                "produced_qty",
                "production_type",
                "routing_id",
            };
            var qPage = new
            {
                limit = 10000,
                offset = 0,
                order = "name desc",
            };

            var resp = await CallSearchRead("mrp.production", qDomain, qFields, qPage);
            if (resp.ContainsKey("error"))
            {
                var message = $"【拉取单据】{resp["error"].ToString()}";
                throw new AppException(message);
            }
            var res = (JArray)resp["result"];
            if (res == null || res.Count <= 0)
            {
                return null;
            }
            var r = new List<object>();
            var Product = "";
            for (var i = 0; i < res.Count; i++)
            {
                var x = (JObject)res[i];
                r.Add(new
                {
                    DianduNo = x["name"].ToString(),
                    ProductId = x["product_id"] is JArray ? JArray.FromObject(x["product_id"])[1].ToString() : "",
                    Grade = x["grade"] is JArray ? JArray.FromObject(x["grade"])[1].ToString() : "",
                    Spec = x["prodcut_spec"].ToString(),
                    IncomeQty = (int)x["produced_qty"],
                });
            }
            return new
            {
                rows = r,
                total = res.Count
            };
        }



        /// <summary>
        /// 同步生产任务单
        /// </summary>
        /// 
        public async Task<object> SyncProductionTask(string taskNo = "")
        {
            var isSingle = taskNo.IsValuable();

            //同步的任务工序
            var typeArray = new[] { "powder" };
            //var typeArray = new[] { "white" };

            var qDomain = new List<object> {

                new List<object> { "production_type", "in", typeArray }
            };

            if (isSingle)
            {
                qDomain.Add(new List<object> { "name", "=", taskNo });
            }
            else
            {
                qDomain.Add(new List<object> { "state", "=", "in_production" });
            }

            var qFields = new List<string> {
                "grade",
                "prodcut_spec",
                "raw_resume_weight",
                "state",
                "schedule_id",
                "product_id",
                "partner_id",
                "name",
                "raw_lot_id",
                "date_planned",
                "product_qty",
                "production_type",
                "routing_id",
            };
            var qPage = new
            {
                limit = 10000,
                offset = 0,
                order = "name desc",
            };

            var resp = await CallSearchRead("mrp.production", qDomain, qFields, qPage);
            if (resp.ContainsKey("error"))
            {
                var message = $"【拉取单据】{resp["error"].ToString()}";
                throw new AppException(message);
            }
            var res = (JArray)resp["result"];
            if (res == null || res.Count <= 0)
            {
                return null;
            }
            var r = new List<object>();
            for (var i = 0; i < res.Count; i++)
            {
                var x = (JObject)res[i];
                r.Add(new
                {
                    WorkOrder = x["name"].ToString(),
                    Product = x["product_id"] is JArray ? JArray.FromObject(x["product_id"])[1].ToString() : "",
                    Qty = x["product_qty"].ToString(),
                    LotNo = x["raw_lot_id"] is JArray ? JArray.FromObject(x["raw_lot_id"])[1].ToString() : "",
                    SendTime = x["date_planned"].ToString().Substring(0, 10),
                    SendWeight = x["raw_resume_weight"].ToString()
                });
            }
            return new
            {
                rows = r,
                total = res.Count
            };
        }
    }
}
